<?php
/**
 * Produces the provider declaration for a DB.
 *
 * FEATURE: This is only known to support MySQL for now (other DBs may likely produce invalid results)
 */
require_once dirname(__FILE__).'/php_support/error_handling.inc';

require_once 'MDB2.php';

function perror( $msg ) {
	file_put_contents( 'php://stderr', $msg );
}

if( $argc < 3 ) {
	perror( "Syntax: {$argv[0]} provider_name dsn
	
DSN Example: mysqli://DBSTestUser:password@localhost/dbs_test
" );
	exit(1);
}

function check_error( $res ) {
	if( !@PEAR::isError( $res ) ) 
		return true;
		
	perror( $res->getMessage() );
	perror( $res->userinfo );	//why is this not part of getMessage?! (TODO: move into the DBScheme adapter for MDB2)
	exit(1);
}

$typeMap = array( 
	'int' => 'Integer',
	'int2' => 'Integer',
	'int4' => 'Integer',
	'int8' => 'Integer',
	'tinyint' => 'Integer',
	'smallint' => 'Integer',
	'mediumint' => 'Integer',
	'bigint' => 'Integer',
	'char' => 'String',
	'varchar' => 'String',
	'bpchar' => 'String',
	'tinytext' => 'String',
	'text' => 'Text',
	'mediumtext' => 'Text',
	'longtext' => 'Text',
	'date' => 'Date',
	'time' => 'Time',
	'datetime' => 'DateTime',
	'timestamp' => 'DateTime',
	'numeric' => 'Decimal',
	'decimal' => 'Decimal',
	'float8' => 'Float',
	'float' => 'Float',
	'double' => 'Float',
	'bool' => 'Bool',
	'boolean' => 'Bool',	//NOTE: MySQL bool is TINYINT -- we can't tell
	'blob' => 'Binary',
	'longblob' => 'Binary',
	'tinyblob' => 'Binary',
	'varbinary' => 'Binary',
	'binary' => 'Binary',
	'mediumblob' => 'Binary',
	'enum' => 'String',	//For now we don't fully support enums...
	);
$provider = $argv[1];
$dsn = $argv[2];

//turn off all portability to get most correct representation
$mdb = @MDB2::factory( $dsn, array( 'portability' => MDB2_PORTABILITY_NONE ) );
check_error( $mdb );
$mdb->loadModule('Manager');
$mdb->loadModule('Reverse');

print( "/* File generated by dump_provider */\n" );
print( "provider $provider {
	definition incomplete;
	dbType {$mdb->dbsyntax};
" );

$tables = $mdb->listTables();
check_error( $tables );
$views = $mdb->listViews();
check_error( $views );
$tablesViews = array_merge( $tables, $views );
foreach( $tablesViews as $table ) {
	print( "\ttable $table {\n" );
	//NOTE: http://pear.php.net/bugs/bug.php?id=15100
	$mdb->setOption( 'quote_identifier', true );
	$fields = $mdb->listTableFields( $table );
	check_error( $fields );
	foreach( $fields as $field ) {
		
		//obtain definition
		$decl = $mdb->getTableFieldDefinition( $table, $field );
		check_error( $decl );
		$decl = $decl[0];
		
		//determine native type
		if( !array_key_exists( $decl['nativetype'], $typeMap ) ) {
			perror( "WARNING: Unknown nativetype: {$decl['nativetype']}\n" );
			print( "\t\t/*Omitting $field: Unknown nativetype: {$decl['nativetype']}*/\n" );
			continue;
		}
		$type = $typeMap[$decl['nativetype']];
		$ext = '';
		
		//TODO: skip for now since not supported
		if( $type == 'Binary' )
		{
			perror( "WARNING: Omitting $field: Binary fields not yet supported\n" );
			print( "\t\t/*Omitting $field: Binary fields not yet supported*/\n" );
			continue;	
		}	
			
		//consider Decimals with no fractional part to be Integers
		if( $type == 'Decimal' && isset( $decl['length'] ) ) {
			$digits = split( ',', $decl['length'] );
			if( count( $digits ) < 2 || $digits[1] == 0 )
				$type = 'Integer';
		}
			
		//consider autincrement fields to be last_insert_id
		if( isset($decl['autoincrement']) && $decl['autoincrement'] )
			$ext = ' LAST_INSERT_ID';
			
		//write defintion
		print( "\t\t$field<$type>$ext;\n" );
	}	
	print( "\t}\n" );
}
print( "}\n" );

?>
